package com.serverdemo.application.login;

import com.serverdemo.application.common.*;
import com.serverdemo.core.entity.SocketEntity;
import com.serverdemo.core.entity.SocketEntityStatusEnum;
import com.serverdemo.core.processor.AbstractProcessor;
import com.serverdemo.core.processor.AbstractProcessorMessage;
import com.serverdemo.core.processor.ProcessorManager;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * Created by wangqiang on 2020/4/10.
 */
public class LoginProcessor extends AbstractProcessor
{
    private ConcurrentLinkedQueue<SocketEntity> socketEntities = new ConcurrentLinkedQueue<SocketEntity>();

    private ArrayList<LoginObject> loginObjects = new ArrayList<LoginObject>();

    private LinkedList<LoginObject> waitDeleteLoginObjects = new LinkedList<LoginObject>();

    @Override
    public void init()
    {
        super.init();
    }

    @Override
    public void tick(int interval)
    {
        try
        {
            super.tick(interval);
            tickAdd(interval);
            tickLoginObject(interval);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    private void tickLoginObject(int interval)
    {
        if (loginObjects.isEmpty())
        {
            return;
        }

        int size = loginObjects.size();
        for (int i = 0; i < size; i++)
        {
            LoginObject loginObject = loginObjects.get(i);
            if (loginObject != null)
            {
                if (loginObject.getSocketStatus() == SocketEntityStatusEnum.EXCEPTION)
                {
                    // 异常,需要删除
                    waitDeleteLoginObjects.add(loginObject);
                    continue;
                }
                else
                {
                    loginObject.processInput();

                    loginObject.processOutput();
                }

                if (loginObject.isLoginDone())
                {
                    waitDeleteLoginObjects.add(loginObject);
                    // 发送到场景
                    LSEnterSceneRequest request = new LSEnterSceneRequest();
                    request.setSocketEntity(loginObject.getSocketEntity());
                    request.setUserName(loginObject.getUserName());
                    request.setData(loginObject.getData());
                    ProcessorManager.getInstance().sendMessage(ProcessorManager.getInstance().getSceneProcessor(),
                            request);
                }
            }
        }

        size = waitDeleteLoginObjects.size();
        if (size > 0)
        {
            for (int i = 0; i < size; i++)
            {
                LoginObject loginObject = waitDeleteLoginObjects.get(i);
                loginObject.setSocketEntity(null);
                loginObjects.remove(loginObject);
            }
            waitDeleteLoginObjects.clear();
        }

    }

    private void tickAdd(int interval)
    {
        for (int i = 0; i < 100; i++)
        {
            SocketEntity socketEntity = socketEntities.poll();
            if (socketEntity == null)
            {
                return;
            }

            LoginObject loginObject = new LoginObject();
            loginObject.setSocketEntity(socketEntity);
            loginObjects.add(loginObject);
        }

    }

    public void dispatchMessage(AbstractProcessorMessage message)
    {
        int messageID = message.getMessageID();
        switch (messageID)
        {
            case MessageIDConst.DL_OPERATE_PLAYER_DATA_RESPONSE:
            {
                DLOperatePlayerDataResponse response = (DLOperatePlayerDataResponse) message;
                operatePlayerDataResponse(response);
                break;
            }
        }
    }

    @Override
    public void addSocketEntity(SocketEntity socketEntity)
    {
        socketEntities.add(socketEntity);
    }

    private void operatePlayerDataResponse(DLOperatePlayerDataResponse response)
    {
        String userName = response.getUserName();
        LoginObject loginObject = getLoginObjectFromUserName(userName);
        if (loginObject == null)
        {
            return;
        }

        DBOperateTypeEnum operateType = response.getOperateType();
        switch (operateType)
        {
            case LOAD_PLAYER_DATA:
            {
                loginObject.loadPlayerDataResponse(response);
                break;
            }
            case CREATE_ROLE:
            {
                loginObject.createRoleResponse(response);
                break;
            }
        }
    }

    public LoginObject getLoginObjectFromUserName(String userName)
    {
        int size = loginObjects.size();
        for (int i = 0; i < size; i++)
        {
            LoginObject loginObject = loginObjects.get(i);
            if (loginObject == null)
            {
                continue;
            }
            if (userName.equals(loginObject.getUserName()))
            {
                return loginObject;
            }
        }
        return null;
    }
}
